package com.mingyuan.library.infra.lending.patron.repository;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mingyuan.library.domain.common.event.DomainEvents;
import com.mingyuan.library.domain.lending.patron.event.PatronCreated;
import com.mingyuan.library.domain.lending.patron.event.PatronEvent;
import com.mingyuan.library.domain.lending.patron.model.aggregate.Patron;
import com.mingyuan.library.domain.lending.patron.repository.PatronRepository;
import com.mingyuan.library.infra.lending.patron.convert.PatronInfraConvert;
import com.mingyuan.library.infra.lending.patron.entity.PatronDatabaseEntity;
import com.mingyuan.library.infra.lending.patron.mapper.PatronDatabaseEntityMapper;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

import java.util.UUID;

import static io.vavr.API.*;
import static io.vavr.Predicates.instanceOf;

/**
 * 读者仓储相关接口
 * @author yangzk
 * @version 1.0.0
 * @date 2024.01.16 14:37
 */
@Repository
public class PatronRepositoryImpl extends ServiceImpl<PatronDatabaseEntityMapper,PatronDatabaseEntity> implements PatronRepository {

    /**
     * 领域事件
     */
    @Resource
    private DomainEvents domainEvents;

    @Override
    public Patron find(UUID patronId) {
        return null;
    }

    @Override
    public Patron publish(PatronEvent patronEvent) {
        Patron result = Match(patronEvent).of(
                // 如果是创建读者 创建新读者
                Case($(instanceOf(PatronCreated.class)), this::createNewPatron),
                // 处理下一个事件
                Case($(), this::handleNextEvent));
        // 发布广播事件
        this.domainEvents.publish(patronEvent.normalize());
        return result;
    }

    /**
     * 下一个处理事件
     * @author yangzk
     * @param domainEvent 领域事件
     * @date 2023/12/28 19:28
     **/
    private Patron handleNextEvent(PatronEvent domainEvent) {
        // 根据读者ID查询读者数据库实体信息
        PatronDatabaseEntity entity = this.getBaseMapper().findByPatronId(domainEvent.patronId().getPatronId());
        // 处理
        entity = entity.handle(domainEvent);
        //
        this.save(entity);
        return PatronInfraConvert.INSTANCE.map(entity);
    }

    /**
     * 创建新读者
     * @author yangzk
     * @param domainEvent 读者创建事件
     * @date 2023/12/28 18:57
     * @return 读者信息
     **/
    private Patron createNewPatron(PatronCreated domainEvent) {
        // 组装读者信息
        PatronDatabaseEntity patronDatabaseEntity = new PatronDatabaseEntity(domainEvent.patronId(), domainEvent.getPatronType());
        // 创建读者数据库实体信息并保存
        this.save(patronDatabaseEntity);
        // 转换模型
        return PatronInfraConvert.INSTANCE.map(patronDatabaseEntity);
    }
}
